<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>智能蛇 | hez2010</title>
  
  
  
  <!--link rel="stylesheet" href="//cdn.jsdelivr.net/highlight.js/9.10.0/styles/github-gist.min.css"-->
  
<link rel="stylesheet" href="//cdn.jsdelivr.net/highlight.js/9.10.0/styles/github-gist.min.css">

  
<link rel="stylesheet" href="/css/style.css">

<!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 5.1.1"></head>

<body>
<div class="Shell">
    <aside class='SideBar'>
    <section class='avatar' style="background-image: url()">
        <div class='av-pic' style="background-image: url(/assets/avatar.jpg)">
        </div>
    </section>
    <section class='menu'>
        <div>hez2010</div>
        
            <div>软件工程导论</div>
        
        <ul>
          
            <a href="/" class="Btn">
              <li>Home</li>
            </a>  
          
            <a href="/archives/" class="Btn">
              <li>Archive</li>
            </a>  
          
        </ul>
    </section>
    <section class="media">
        
            
                <a target="_blank" rel="noopener" href="https://github.com/hez2010">
                    <img src="/assets/github.svg" />
                </a>
            
        
    </section>
</aside>

    <div class="container">
        <div data-pager-shell>
            <div>
  <article class='ContentView'>
    <header class='PageTitle'>
        <h1>智能蛇</h1>
    </header>

    <section>
      <h1 id="C-编写智能贪吃蛇小游戏"><a href="#C-编写智能贪吃蛇小游戏" class="headerlink" title="C 编写智能贪吃蛇小游戏"></a>C 编写智能贪吃蛇小游戏</h1><p>项目代码见：<a target="_blank" rel="noopener" href="https://gitee.com/hez2010/snake_ai">https://gitee.com/hez2010/snake_ai</a></p>
<h2 id="整体框架"><a href="#整体框架" class="headerlink" title="整体框架"></a>整体框架</h2><p>智能蛇的流程如下：</p>
<ol>
<li>清除屏幕</li>
<li>生成食物</li>
<li>输出地图</li>
<li>如果游戏未结束<ol>
<li>延时 1 秒</li>
<li>决策下一步并移动蛇，如果无法找出下一步则游戏结束</li>
<li>如果吃到食物则更新蛇的长度并生成新食物，如果蛇长度超过限制则游戏结束</li>
<li>清除屏幕</li>
<li>输出移动后的地图</li>
<li>重复上述过程</li>
</ol>
</li>
<li>如果游戏结束输出 <code>Game Over!!</code></li>
</ol>
<a id="more"></a>

<p>因此，会吃的蛇设计为以下几个函数：</p>
<ul>
<li><code>print_map</code> 输出地图</li>
<li><code>snake_mode</code> 移动蛇</li>
<li><code>game_over</code> 结束游戏</li>
<li><code>generate_food</code> 生成食物</li>
<li><code>where_go_next</code> 决策下一步移动</li>
</ul>
<p>用代码表示为：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;\033[2J&quot;</span>);<br>generate_food();<br>print_map();<br><span class="hljs-keyword">while</span> (!gameOver) &#123;<br>    sleep(<span class="hljs-number">1</span>);<br>    input = where_go_next();<br>    <span class="hljs-keyword">switch</span> (input) &#123;<br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;A&#x27;</span>: <span class="hljs-comment">// 向左移动</span><br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;a&#x27;</span>:<br>        snake_move(<span class="hljs-number">0</span>, <span class="hljs-number">-1</span>);<br>        <span class="hljs-keyword">break</span>;<br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;D&#x27;</span>: <span class="hljs-comment">// 向右移动</span><br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;d&#x27;</span>:<br>        snake_move(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>);<br>        <span class="hljs-keyword">break</span>;<br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;W&#x27;</span>: <span class="hljs-comment">// 向上移动</span><br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;w&#x27;</span>:<br>        snake_move(<span class="hljs-number">-1</span>, <span class="hljs-number">0</span>);<br>        <span class="hljs-keyword">break</span>;<br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;S&#x27;</span>: <span class="hljs-comment">// 向下移动</span><br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;s&#x27;</span>:<br>        snake_move(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>);<br>        <span class="hljs-keyword">break</span>;<br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;Q&#x27;</span>:<br>    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;q&#x27;</span>:<br>        gameOver = <span class="hljs-number">1</span>;<br>        <span class="hljs-keyword">break</span>;<br>    <span class="hljs-keyword">default</span>:<br>        <span class="hljs-keyword">continue</span>;<br>    &#125;<br>    <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;\033[2J&quot;</span>);<br>    print_map();<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="清除屏幕"><a href="#清除屏幕" class="headerlink" title="清除屏幕"></a>清除屏幕</h3><p>在 Linux 下可以通过输出 <code>\033[2J</code> 来清除屏幕。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;\033[2J&quot;</span>);<br></code></pre></td></tr></table></figure>

<h3 id="输出地图"><a href="#输出地图" class="headerlink" title="输出地图"></a>输出地图</h3><p>首先利用打表的方式存储空地图：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-comment">// 初始地图</span><br><span class="hljs-keyword">char</span> <span class="hljs-built_in">map</span>[<span class="hljs-number">12</span>][<span class="hljs-number">12</span>] = &#123;<br>    <span class="hljs-string">&quot;************&quot;</span>,<br>    <span class="hljs-string">&quot;*          *&quot;</span>,<br>    <span class="hljs-string">&quot;*       *  *&quot;</span>,<br>    <span class="hljs-string">&quot;*    *     *&quot;</span>,<br>    <span class="hljs-string">&quot;*          *&quot;</span>,<br>    <span class="hljs-string">&quot;*          *&quot;</span>,<br>    <span class="hljs-string">&quot;*   *      *&quot;</span>,<br>    <span class="hljs-string">&quot;*          *&quot;</span>,<br>    <span class="hljs-string">&quot;*       *  *&quot;</span>,<br>    <span class="hljs-string">&quot;*    *     *&quot;</span>,<br>    <span class="hljs-string">&quot;*          *&quot;</span>,<br>    <span class="hljs-string">&quot;************&quot;</span><br>&#125;;<br></code></pre></td></tr></table></figure>

<p>为了记录蛇的位置，可以利用数组分别保存蛇的行列坐标：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-comment">// 蛇身体的行坐标</span><br><span class="hljs-keyword">int</span> snakeX[SNAKE_MAX_LEN] = &#123; <span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span> &#125;;<br><br><span class="hljs-comment">// 蛇身体的列坐标</span><br><span class="hljs-keyword">int</span> snakeY[SNAKE_MAX_LEN] = &#123; <span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span> &#125;;<br></code></pre></td></tr></table></figure>

<p>再用 <code>foodX</code> 和 <code>foodY</code> 保存食物的行列坐标：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-comment">// 食物的行列坐标</span><br><span class="hljs-keyword">int</span> foodX = <span class="hljs-number">0</span>, foodY = <span class="hljs-number">0</span>;<br></code></pre></td></tr></table></figure>

<p>这样一来，只需要判断坐标点是否记录在 <code>snakeX</code> 和 <code>snakeY</code> 中即可知道对应位置是不是蛇，根据 <code>foodX</code> 和 <code>foodY</code> 即可判断是不是食物：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-keyword">if</span> (snakeX[k] == i &amp;&amp; snakeY[k] == j) &#123;<br>    ch = k == snakeLength - <span class="hljs-number">1</span> ? SNAKE_HEAD : SNAKE_BODY;<br>&#125;<br><span class="hljs-keyword">if</span> (i == foodX &amp;&amp; j == foodY) &#123;<br>    ch = SNAKE_FOOD;<br>&#125;<br></code></pre></td></tr></table></figure>


<p>然后根据位置输出对应的字符即可。</p>
<h3 id="移动蛇"><a href="#移动蛇" class="headerlink" title="移动蛇"></a>移动蛇</h3><p>移动蛇的步骤为：</p>
<ol>
<li><p>计算蛇头的新位置</p>
 <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-keyword">int</span> i, x = snakeX[snakeLength - <span class="hljs-number">1</span>] + dx, y = snakeY[snakeLength - <span class="hljs-number">1</span>] + dy;<br></code></pre></td></tr></table></figure></li>
<li><p>判断是否吃到食物，若吃到则增加身体长度，若蛇超过最长长度则游戏结束</p>
 <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-keyword">if</span> (x == foodX &amp;&amp; y == foodY) &#123;<br>    <span class="hljs-comment">// 若蛇超过最长长度则游戏结束</span><br>    <span class="hljs-keyword">if</span> (snakeLength + <span class="hljs-number">1</span> == SNAKE_MAX_LEN) &#123;<br>        game_over();<br>        <span class="hljs-keyword">return</span>;<br>    &#125;<br>    snakeX[snakeLength] = x;<br>    snakeY[snakeLength] = y;<br>    snakeLength++;<br>    generate_food();<br>    <span class="hljs-keyword">return</span>;<br>&#125;<br></code></pre></td></tr></table></figure>
</li>
<li><p>判断是否撞到障碍物，若撞到则游戏结束</p>
 <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-keyword">if</span> (<span class="hljs-built_in">map</span>[x][y] == <span class="hljs-string">&#x27;*&#x27;</span>) &#123;<br>    game_over();<br>    <span class="hljs-keyword">return</span>;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>判断是否撞到自身，若撞到则游戏结束</p>
 <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-keyword">for</span> (i = <span class="hljs-number">1</span>; i &lt; snakeLength; i++) &#123;<br>    <span class="hljs-keyword">if</span> (snakeX[i] == x &amp;&amp; snakeY[i] == y) &#123;<br>        game_over();<br>        <span class="hljs-keyword">return</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>更新蛇的位置</p>
 <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; snakeLength - <span class="hljs-number">1</span>; i++) &#123;<br>    snakeX[i] = snakeX[i + <span class="hljs-number">1</span>];<br>    snakeY[i] = snakeY[i + <span class="hljs-number">1</span>];<br>&#125;<br>snakeX[snakeLength - <span class="hljs-number">1</span>] = x;<br>snakeY[snakeLength - <span class="hljs-number">1</span>] = y;<br></code></pre></td></tr></table></figure>

</li>
</ol>
<h3 id="结束游戏"><a href="#结束游戏" class="headerlink" title="结束游戏"></a>结束游戏</h3><p>程序中利用一个全局变量 <code>gameOver</code> 指示游戏是否结束，因此结束游戏只需要将这个变量设置为 <code>1</code> 即可。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">game_over</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>&#123;<br>    gameOver = <span class="hljs-number">1</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="生成食物"><a href="#生成食物" class="headerlink" title="生成食物"></a>生成食物</h3><p>生成的食物需要确保食物出现在空白的位置，这个位置不能和蛇所在的位置重叠，也不能和障碍物重叠，因此只需要不断获取随机数直到找到满足要求的位置即可。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">generate_food</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span> </span>&#123;<br>    <span class="hljs-keyword">int</span> canPlaceFood, i;<br>    <span class="hljs-keyword">do</span> &#123;<br>        canPlaceFood = <span class="hljs-number">1</span>;<br>        foodX = rand() % <span class="hljs-number">10</span> + <span class="hljs-number">1</span>;<br>        foodY = rand() % <span class="hljs-number">10</span> + <span class="hljs-number">1</span>;<br>        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">map</span>[foodX][foodY] == <span class="hljs-string">&#x27;*&#x27;</span>) &#123;<br>            canPlaceFood = <span class="hljs-number">0</span>;<br>        &#125;<br>        <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; snakeLength; i++) &#123;<br>            <span class="hljs-keyword">if</span> (snakeX[i] == foodX &amp;&amp; snakeY[i] == foodY) &#123;<br>                canPlaceFood = <span class="hljs-number">0</span>;<br>                <span class="hljs-keyword">break</span>;<br>            &#125;<br>        &#125;<br>    &#125; <span class="hljs-keyword">while</span> (!canPlaceFood);<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="决策下一步"><a href="#决策下一步" class="headerlink" title="决策下一步"></a>决策下一步</h3><p>决策下一步需要确保移动后蛇不会撞到自身，也不会撞到障碍物，并且要尽可能距离食物更进一步。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">char</span> <span class="hljs-title">where_go_next</span><span class="hljs-params">()</span> </span>&#123;<br>    <span class="hljs-keyword">char</span> movable[] = &#123; <span class="hljs-string">&#x27;a&#x27;</span>,<span class="hljs-string">&#x27;d&#x27;</span>,<span class="hljs-string">&#x27;w&#x27;</span>,<span class="hljs-string">&#x27;s&#x27;</span> &#125;;<br>    <span class="hljs-comment">// 移动方向</span><br>    <span class="hljs-keyword">int</span> dx[] = &#123; <span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">-1</span>,<span class="hljs-number">1</span> &#125;;<br>    <span class="hljs-keyword">int</span> dy[] = &#123; <span class="hljs-number">-1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span> &#125;;<br>    <span class="hljs-comment">// 距离食物的位置</span><br>    <span class="hljs-keyword">int</span> distance[] = &#123; <span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span> &#125;;<br>    <span class="hljs-keyword">int</span> i, j;<br>    <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">4</span>; i++) &#123;<br>        <span class="hljs-comment">// 计算新位置</span><br>        <span class="hljs-keyword">int</span> x = snakeX[snakeLength - <span class="hljs-number">1</span>] + dx[i], y = snakeY[snakeLength - <span class="hljs-number">1</span>] + dy[i];<br>        <span class="hljs-comment">// 计算距离食物的位置</span><br>        distance[i] = <span class="hljs-built_in">abs</span>(foodX - x) + <span class="hljs-built_in">abs</span>(foodY - y);<br>        <span class="hljs-comment">// 不能撞到障碍物</span><br>        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">map</span>[x][y] == <span class="hljs-string">&#x27;*&#x27;</span>) &#123;<br>            distance[i] = <span class="hljs-number">9999</span>;<br>        &#125;<br>        <span class="hljs-comment">// 不能撞到自身</span><br>        <span class="hljs-keyword">for</span> (j = <span class="hljs-number">1</span>; j &lt; snakeLength; j++) &#123;<br>            <span class="hljs-keyword">if</span> (snakeX[j] == x &amp;&amp; snakeY[j] == y) &#123;<br>                distance[i] = <span class="hljs-number">9999</span>;<br>                <span class="hljs-keyword">break</span>;<br>            &#125;<br>        &#125;<br>    &#125;<br><br>    <span class="hljs-comment">// 找出移动后可以使蛇头距离食物最近的方向</span><br>    <span class="hljs-keyword">int</span> k = <span class="hljs-number">-1</span>;<br>    <span class="hljs-keyword">int</span> minValue = <span class="hljs-number">9999</span>;<br>    <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">4</span>; i++) &#123;<br>        <span class="hljs-keyword">if</span> (distance[i] &lt; minValue) &#123;<br>            k = i;<br>            minValue = distance[i];<br>        &#125;<br>    &#125;<br><br>    <span class="hljs-comment">// 如果找不到则游戏结束</span><br>    <span class="hljs-keyword">return</span> k == <span class="hljs-number">-1</span> ? <span class="hljs-string">&#x27;q&#x27;</span> : movable[k];<br>&#125;<br></code></pre></td></tr></table></figure>

<h2 id="效果测试"><a href="#效果测试" class="headerlink" title="效果测试"></a>效果测试</h2><p>减少 <code>sleep</code> 时间后，测试效果如下：</p>
<p><img src="/assets/snake_ai/1.gif" alt="1"></p>
<h3 id="一个长度为5的障碍物能困死该自动跑的蛇吗"><a href="#一个长度为5的障碍物能困死该自动跑的蛇吗" class="headerlink" title="一个长度为5的障碍物能困死该自动跑的蛇吗"></a>一个长度为5的障碍物能困死该自动跑的蛇吗</h3><p>游戏地图为 12*12，空白区域为 10*10，长度为5的障碍物不会困死蛇，但是随着蛇的长度变长（超过5），蛇可能会把自己困死，例如下面这种情况：</p>
<p><img src="/assets/snake_ai/2.png" alt="1"></p>
<h2 id="kbhit-实现"><a href="#kbhit-实现" class="headerlink" title="kbhit 实现"></a>kbhit 实现</h2><p>利用 <code>kbhit()</code> 可以检测 TTY 的输入，实现非阻塞地检测键盘输入。通过调用 <code>kbhit</code> 函数可以不需要回车就能捕获到用户输入。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs c"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>&#123;<br>        <span class="hljs-comment">// 设置终端进入非缓冲状态</span><br>        <span class="hljs-keyword">int</span> tty_set_flag;<br>        tty_set_flag = tty_set();<br><br>        <span class="hljs-keyword">while</span>(<span class="hljs-number">1</span>) &#123;<br>                <span class="hljs-keyword">if</span>(kbhit()) &#123;<br>                        <span class="hljs-keyword">char</span> key = getchar();<br>                        <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;%c pressed\n&quot;</span>, key);<br>                        <span class="hljs-keyword">if</span>(key == <span class="hljs-string">&#x27;q&#x27;</span>)<br>                                <span class="hljs-keyword">break</span>;<br>                &#125; <span class="hljs-keyword">else</span> &#123;<br>                       ;<span class="hljs-comment">// fprintf(stderr, &quot;&lt;no key detected&gt;\n&quot;);</span><br>                &#125;<br>        &#125;<br><br>        <span class="hljs-comment">// 恢复终端设置</span><br>        <span class="hljs-keyword">if</span>(tty_set_flag == <span class="hljs-number">0</span>) <br>                tty_reset();<br>        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>&#125;<br></code></pre></td></tr></table></figure>



      

    </section>
    
      <section class='ArticleMeta'>
          <div>
            发布于&nbsp;
            <time datetime="2021-01-05T13:27:38.939Z" itemprop="datePublished">
              2021-01-05
            </time>
          </div>
          
      </section>
    
    
</article>

  
</div>

            <footer>
    <div>© 2021 - Steven He </div>
    <div>
        <span>
            Powered by <a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a>
        </span>
        ,
        <span>
            Theme - <a target="_blank" rel="noopener" href="https://github.com/nameoverflow/hexo-theme-icalm">Icalm</a>
        </span>
    </div>
</footer>

        </div>
    </div>
</div>

<script src="/js/pager/dist/singlepager.js"></script>

<script>
var sp = new Pager('data-pager-shell')

</script>
</body>
</html>